

package VisAVisTab;


import com.hp.hpl.jena.ontology.*;
import com.hp.hpl.jena.rdf.model.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

import edu.stanford.smi.protege.util.*;
import java.awt.datatransfer.*;
import java.awt.dnd.*;
import java.io.*;
import java.util.*;
import javax.swing.tree.*;



public class OntologyPanel extends JPanel implements TreeSelectionListener,ActionListener,DragSourceListener, DragGestureListener {
    
    JScrollPane spCls,spProp ;
    JTabbedPane jp=new JTabbedPane(JTabbedPane.TOP);
    
    JTree ontTree,propTree;
    OntModel ontModel,loadedOntModel;
    DefaultTreeModel treeModel,propModel;
    ClassHierarchy ch=new ClassHierarchy();
    PropertyHierarchy ph = new PropertyHierarchy();
    DragSource dragSource=new DragSource();
    JTextArea infoArea;
    String newFilePath,loadedFile;
    JButton openButton,loadButton,saveButton;
    Vector mapVector=new Vector();
    JList mapList=new JList(mapVector);
    JMenuItem removeMenuItem,removeAllMenuItem;
    Map prefixMap;
    String oldFilePath=new String();
    JTextField txtDB,txtFile;
    JTextArea txtVersion;
    
    public OntologyPanel() {
        
        
        GridBagLayout gridbag=new GridBagLayout();
        GridBagConstraints constraints=new GridBagConstraints();
        setLayout(gridbag);
        
        ontTree =new JTree(treeModel);
        ontTree.setCellRenderer(new OntTreeCellRenderer());
        ontTree.setEditable(false);
        ontTree.setRootVisible(true);
        ontTree.setShowsRootHandles(true);
        ontTree.putClientProperty("JTree.lineStyle", "Angled");
        ontTree.addTreeSelectionListener(this);
        
        propTree =new JTree(propModel);
        propTree.setCellRenderer(new OntTreeCellRenderer());
        propTree.setEditable(false);
        propTree.setRootVisible(false);
        propTree.setShowsRootHandles(true);
        propTree.putClientProperty("JTree.lineStyle", "Angled");
        propTree.addTreeSelectionListener(this);
        
        spCls = new JScrollPane(ontTree);
        spProp = new JScrollPane(propTree);
        
        openButton = new JButton();
        openButton.setText(null);
        openButton.setToolTipText("Open base ontology");
        openButton.setIcon(ComponentUtilities.loadImageIcon(OntologyPanel.class,"resource/project.open.gif"));
        openButton.setSize(10,10);
        openButton.addActionListener(this);
        
        loadButton = new JButton();
        loadButton.setText(null);
        loadButton.setToolTipText("Load an existing mapping file");
        loadButton.setIcon(ComponentUtilities.loadImageIcon(OntologyPanel.class,"resource/OpenProject.gif"));
        loadButton.setSize(10,10);
        loadButton.addActionListener(this);
        
        saveButton = new JButton();
        saveButton.setText(null);
        saveButton.setToolTipText("Save all mappings to an OWL file");
        saveButton.setIcon(ComponentUtilities.loadImageIcon(OntologyPanel.class,"resource/SaveProject.gif"));
        saveButton.setSize(10,10);
        saveButton.addActionListener(this);
        
        jp.addTab("Classes",spCls);
        jp.addTab("Properties",spProp);
        jp.setToolTipText("Drag a class and drop it to the \"MapTo\" textfield");
        
        
        buildConstraints(constraints,0,0,1,1,100,4,GridBagConstraints.NONE);
        gridbag.setConstraints(openButton,constraints);
        add(openButton);
        
        buildConstraints(constraints,1,0,1,1,100,0,GridBagConstraints.NONE);
        gridbag.setConstraints(loadButton,constraints);
        add(loadButton);
        
        buildConstraints(constraints,2,0,1,1,100,0,GridBagConstraints.NONE);
        gridbag.setConstraints(saveButton,constraints);
        add(saveButton);
        
        //JLabel label1=new JLabel("Class Hierarchy");
        JLabel label2=new JLabel("Mappings List");
        JLabel label3=new JLabel("Ontology Description");
        
        /*buildConstraints(constraints,0,1,3,1,100,3,GridBagConstraints.NONE);
        gridbag.setConstraints(label1,constraints);
        add(label1);*/
        
        buildConstraints(constraints,3,1,2,1,100,3,GridBagConstraints.NONE);
        gridbag.setConstraints(label2,constraints);
        add(label2);
        
        buildConstraints(constraints,0,1,3,6,100,70,GridBagConstraints.BOTH);
        gridbag.setConstraints(jp,constraints);
        add(jp);
        
        
        
        dragSource.addDragSourceListener(this);
        dragSource.createDefaultDragGestureRecognizer( ontTree, DnDConstants.ACTION_MOVE, this);
        
        infoArea= new JTextArea((String)null);
        infoArea.setEditable(false);
        infoArea.setToolTipText("Info for the selected node of the tree");
        JScrollPane p3 = new JScrollPane(infoArea);
        
        JPopupMenu popup=new JPopupMenu();
        removeMenuItem = new JMenuItem("Remove");
        removeMenuItem.addActionListener(this);
        popup.add(removeMenuItem);
        removeAllMenuItem = new JMenuItem("Remove All");
        removeAllMenuItem.addActionListener(this);
        popup.add(removeAllMenuItem);
        
        
        MouseListener popupListener = new PopupListener(popup,mapList);
        mapList.addMouseListener(popupListener);
        
        JScrollPane mapPanel=new JScrollPane(mapList);
        mapList.setToolTipText("Right-click on one of the mappings to remove it");
        
        
        buildConstraints(constraints,3,2,2,2,100,52,GridBagConstraints.BOTH);
        gridbag.setConstraints(mapPanel,constraints);
        add(mapPanel);
        
        JLabel label4 = new JLabel("Last Modified:");
        JLabel label5 = new JLabel("DB Type and Name:");
        JLabel label6= new JLabel("Linked To Ontology:");
        txtVersion=new JTextArea();
        txtVersion.setEditable(false);
        txtDB=new JTextField(10);
        txtDB.setEditable(false);
        txtFile=new JTextField(10);
        txtFile.setEditable(false);
        
        buildConstraints(constraints,3,4,1,1,100,5,GridBagConstraints.BOTH);
        gridbag.setConstraints(label4,constraints);
        add(label4);
        
        buildConstraints(constraints,4,4,1,1,100,0,GridBagConstraints.HORIZONTAL);
        gridbag.setConstraints(txtVersion,constraints);
        add(txtVersion);
        
        buildConstraints(constraints,3,5,1,1,100,5,GridBagConstraints.BOTH);
        gridbag.setConstraints(label5,constraints);
        add(label5);
        
        buildConstraints(constraints,4,5,1,1,100,0,GridBagConstraints.HORIZONTAL);
        gridbag.setConstraints(txtDB,constraints);
        add(txtDB);
        
        buildConstraints(constraints,3,6,1,1,100,5,GridBagConstraints.BOTH);
        gridbag.setConstraints(label6,constraints);
        add(label6);
        
        buildConstraints(constraints,4,6,1,1,100,0,GridBagConstraints.HORIZONTAL);
        gridbag.setConstraints(txtFile,constraints);
        add(txtFile);
      /*  JSplitPane split=new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,sp,mapPanel);
        buildConstraints(constraints,0,2,5,6,100,70,GridBagConstraints.BOTH);
        gridbag.setConstraints(split,constraints);
        add(split);*/
        
        
        buildConstraints(constraints,0,8,5,1,100,3,GridBagConstraints.NONE);
        gridbag.setConstraints(label3,constraints);
        add(label3);
        
        buildConstraints(constraints,0,9,5,3,100,20,GridBagConstraints.BOTH);
        gridbag.setConstraints(p3,constraints);
        add(p3);
        
        
        
        
    }
    
    public void buildConstraints(GridBagConstraints gbc,int gx,int gy,int gw,int gh,int wx,int wy,int fill){
        
        gbc.gridx=gx;
        gbc.gridy=gy;
        gbc.gridwidth=gw;
        gbc.gridheight=gh;
        gbc.weightx=wx;
        gbc.weighty=wy;
        gbc.fill=fill;
    }
    
    //// A new node(either class or property) has been selected from the tree and we want to fill
    //the information area below
    public void valueChanged(TreeSelectionEvent e){
        DefaultMutableTreeNode node=new DefaultMutableTreeNode();
        if (jp.getSelectedComponent()==spCls)
            node = (DefaultMutableTreeNode)ontTree.getLastSelectedPathComponent();
        else if (jp.getSelectedComponent()==spProp)
            node = (DefaultMutableTreeNode)propTree.getLastSelectedPathComponent();
        if (node == null)
            return;
        NodeInfo nodeInfo = (NodeInfo)node.getUserObject();
        fillInfoArea(nodeInfo);
        
    }
    
    //whenever a node of the JTree is selected,fill the info area with information about the selected node
    public void fillInfoArea(NodeInfo nodeInfo){
        infoArea.setText(null);
        Font font = getFont();
        //if the selected node is a class
        if (nodeInfo.type==NodeInfo.CLASS){
            ClassInfo classInfo = nodeInfo.classInfo;
            infoArea.setFont(font.deriveFont(Font.PLAIN));
            String localName=classInfo.name.substring(classInfo.name.indexOf('#')+1);
            String totalInfo = "\t\tInfo On Class " + localName +"\n\n";
            totalInfo = totalInfo.concat("Full URI: "+classInfo.name+"\n");
            
            totalInfo = totalInfo.concat("Direct Sublasses: ");
            for (int i=0; i<classInfo.subClasses.size();i++) {
                totalInfo=totalInfo.concat(((Resource)classInfo.subClasses.elementAt(i)).getLocalName());
                if (i!=classInfo.subClasses.size()-1) totalInfo=totalInfo.concat(", ");
            }
            if (classInfo.subClasses.size()==0) totalInfo=totalInfo.concat("-");
            
            //if the class selected is not THING,include superclasses,disjoint classes,restrictions and possible mappings
            if (classInfo.type==ClassInfo.CLASS){
                totalInfo= totalInfo.concat("\nDirect Superclasses: ");
                for (int i=0; i<classInfo.superClasses.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)classInfo.superClasses.elementAt(i)).getLocalName());
                    if (i!=classInfo.superClasses.size()-1) totalInfo=totalInfo.concat(", ");
                }
                
                
                totalInfo= totalInfo.concat("\nDisjoint With: ");
                for (int i=0; i<classInfo.disjoint.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)classInfo.disjoint.elementAt(i)).getLocalName());
                    if (i!=classInfo.disjoint.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (classInfo.disjoint.size()==0) totalInfo=totalInfo.concat("-");
                
                
                totalInfo= totalInfo.concat("\nDeclared Properties: ");
                for (int i=0; i<classInfo.properties.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)classInfo.properties.elementAt(i)).getLocalName());
                    if (i!=classInfo.properties.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (classInfo.properties.size()==0) totalInfo=totalInfo.concat("-");
                
                
                totalInfo= totalInfo.concat("\nRestrictions: ");
                for (int i=0; i<classInfo.restrictions.size();i++) {
                    Restriction current = (Restriction)classInfo.restrictions.elementAt(i);
                    
                    //if the restriction is a allvaluesfrom restriction
                    if (current.isAllValuesFromRestriction()){
                        AllValuesFromRestriction avfr=current.asAllValuesFromRestriction();
                        totalInfo=totalInfo.concat("Property "+avfr.getOnProperty().getLocalName()+" must have all values from ");
                        OntClass res= (OntClass)avfr.getAllValuesFrom();
                        if (res.isUnionClass()){
                            UnionClass uc=res.asUnionClass();
                            Iterator iop=uc.listOperands();
                            while (iop.hasNext()){
                                totalInfo=totalInfo.concat(((Resource)iop.next()).getLocalName());
                                if (iop.hasNext()) totalInfo=totalInfo.concat(" or ");
                            }
                        } else if(!res.isAnon()) totalInfo=totalInfo.concat(res.getLocalName());
                        
                        //if the restriction is a somevaluesfrom restriction
                    } else if (current.isSomeValuesFromRestriction()){
                        SomeValuesFromRestriction svfr=current.asSomeValuesFromRestriction();
                        totalInfo=totalInfo.concat("Property "+svfr.getOnProperty().getLocalName()+" must have some values from ");
                        OntClass res= (OntClass)svfr.getSomeValuesFrom();
                        if (res.isUnionClass()){
                            UnionClass uc=res.asUnionClass();
                            Iterator iop=uc.listOperands();
                            while (iop.hasNext()){
                                totalInfo=totalInfo.concat(((Resource)iop.next()).getLocalName());
                                if (iop.hasNext()) totalInfo=totalInfo.concat(" or ");
                            }
                        } else if (res.isIntersectionClass()){
                            IntersectionClass ic=res.asIntersectionClass();
                            Iterator iop = ic.listOperands();
                            totalInfo=totalInfo.concat("(");
                            while (iop.hasNext()){
                                OntClass cur=(OntClass)iop.next();
                                if (!cur.isAnon()) totalInfo=totalInfo.concat(cur.getLocalName()+" ");
                                else if (cur.isRestriction()){
                                    Restriction res1=cur.asRestriction();
                                    if (res1.isSomeValuesFromRestriction()){
                                        SomeValuesFromRestriction rest=res1.asSomeValuesFromRestriction();
                                        totalInfo=totalInfo.concat("(Property "+rest.getOnProperty().getLocalName()+
                                                "must have some values from "+rest.getSomeValuesFrom().getLocalName()+") ");
                                    }
                                    //more cases are needed to be checked , the above is just suggestive
                                }
                                if (iop.hasNext()) totalInfo=totalInfo.concat("AND ");
                                else totalInfo=totalInfo.concat(")");
                            }
                        } else if(!res.isAnon()) totalInfo=totalInfo.concat(res.getLocalName());
                        
                        //if the restriction is a hasValue restriction
                    } else if (current.isHasValueRestriction()){
                        HasValueRestriction hvr=current.asHasValueRestriction();
                        totalInfo=totalInfo.concat("Property "+hvr.getOnProperty().getLocalName()+" must have value ");
                        if (hvr.getOnProperty().isObjectProperty()){
                            OntResource res = (OntResource)hvr.getHasValue();
                            totalInfo=totalInfo.concat(res.getLocalName());
                        } else if (hvr.getOnProperty().isDatatypeProperty()){
                            RDFNode res = hvr.getHasValue();
                            totalInfo=totalInfo.concat(res.toString());
                        }
                        
                        //if the restriction is a cardinality restriction
                    } else if (current.isCardinalityRestriction()){
                        CardinalityRestriction cr=current.asCardinalityRestriction();
                        totalInfo=totalInfo.concat("Property "+cr.getOnProperty().getLocalName()+" has cardinality ");
                        totalInfo=totalInfo.concat(cr.getCardinality()+"");
                        
                        //if the restriction is a maxcardinality restriction
                    } else if (current.isMaxCardinalityRestriction()){
                        MaxCardinalityRestriction maxcr=current.asMaxCardinalityRestriction();
                        totalInfo=totalInfo.concat("Property "+maxcr.getOnProperty().getLocalName()+" has maximum cardinality ");
                        totalInfo=totalInfo.concat(maxcr.getMaxCardinality()+"");
                        
                        //if the restriction is a mincardinality restriction
                    } else if (current.isMinCardinalityRestriction()){
                        MinCardinalityRestriction mincr=current.asMinCardinalityRestriction();
                        totalInfo=totalInfo.concat("Property "+mincr.getOnProperty().getLocalName()+" has minimum cardinality ");
                        totalInfo=totalInfo.concat(mincr.getMinCardinality()+"");
                    }
                    if (i!=classInfo.restrictions.size()-1) totalInfo=totalInfo.concat("\n                        ");
                }
                if (classInfo.restrictions.size()==0) totalInfo=totalInfo.concat("-");
                
                //write down the mappings
                totalInfo=totalInfo.concat("\nMapped To: ");
                String basePrefix=ontModel.getNsPrefixURI("");
                Property myProp = ontModel.getProperty(basePrefix, "queryString");
                OntClass myClass = ontModel.getOntClass(classInfo.name);
                StmtIterator i = ontModel.listStatements(myClass, myProp, (RDFNode)null);
                if (!i.hasNext()) totalInfo=totalInfo.concat("-");
                while (i.hasNext()){
                    Statement s = i.nextStatement();
                    String mapQuery = s.getString();
                    if (mapQuery.contains("*")){
                        totalInfo=totalInfo.concat("Table(s): ");
                        //get the tables after FROM
                        if (mapQuery.contains("WHERE"))
                            totalInfo=totalInfo.concat(mapQuery.substring(mapQuery.indexOf(" FROM ")+6,mapQuery.indexOf(" WHERE ")));
                        else
                            totalInfo=totalInfo.concat(mapQuery.substring(mapQuery.indexOf(" FROM ")+6));
                    } else{
                        totalInfo=totalInfo.concat("Field(s): ");
                        //find the fields after SELECT
                        totalInfo=totalInfo.concat(mapQuery.substring(7,mapQuery.indexOf(" FROM ")));
                    }
                    if (mapQuery.contains("WHERE")){
                        totalInfo=totalInfo.concat(" with condition(s):");
                        totalInfo=totalInfo.concat(mapQuery.substring(mapQuery.lastIndexOf(" WHERE ")+7));
                    }
                }
                //if the selected node is THING
            } else if (classInfo.type==ClassInfo.THING) {
                totalInfo= totalInfo.concat("\nProperties: ");
                for (int i=0; i<classInfo.properties.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)classInfo.properties.elementAt(i)).getLocalName());
                    if (i!=classInfo.properties.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (classInfo.properties.size()==0) totalInfo=totalInfo.concat("-");
            }
            infoArea.setText(totalInfo);
            
            //if the selected node is a property
        } else if (nodeInfo.type==NodeInfo.PROPERTY){
            PropertyInfo propInfo=nodeInfo.propertyInfo;
            infoArea.setFont(font.deriveFont(Font.PLAIN));
            String localName=propInfo.name.substring(propInfo.name.indexOf('#')+1);
            String totalInfo = "\t\tInfo On Property " + localName +"\n\n";
            totalInfo = totalInfo.concat("Full URI: "+propInfo.name+"\n");
            int type= propInfo.type;
            switch (type){
                case PropertyInfo.DATAT_PROPERTY:
                    totalInfo=totalInfo.concat("Property Type : Datatype\n");
                    break;
                case PropertyInfo.OBJ_PROPERTY:
                    totalInfo=totalInfo.concat("Property Type : Object\n");
                    break;
                case PropertyInfo.ANNOT_PROPERTY:
                    totalInfo=totalInfo.concat("Property Type : Annotation\n");
                    break;
                case PropertyInfo.OTHER:
                    break;
            }
            if (type!=PropertyInfo.ANNOT_PROPERTY){
                
                totalInfo = totalInfo.concat("Subproperties: ");
                for (int i=0; i<propInfo.subProperties.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)propInfo.subProperties.elementAt(i)).getLocalName());
                    if (i!=propInfo.subProperties.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (propInfo.subProperties.size()==0) totalInfo=totalInfo.concat("-");
                
                
                totalInfo = totalInfo.concat("\nSuperproperties: ");
                for (int i=0; i<propInfo.superProperties.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)propInfo.superProperties.elementAt(i)).getLocalName());
                    if (i!=propInfo.superProperties.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (propInfo.superProperties.size()==0) totalInfo=totalInfo.concat("-");
                
                
                totalInfo = totalInfo.concat("\nRange: ");
                for (int i=0; i<propInfo.range.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)propInfo.range.elementAt(i)).getLocalName());
                    if (i!=propInfo.range.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (propInfo.range.size()==0) totalInfo=totalInfo.concat("Thing");
                
                
                totalInfo = totalInfo.concat("\nDomain: ");
                for (int i=0; i<propInfo.domain.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)propInfo.domain.elementAt(i)).getLocalName());
                    if (i!=propInfo.domain.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (propInfo.domain.size()==0) totalInfo=totalInfo.concat("Thing");
                
                
                totalInfo = totalInfo.concat("\nInverse Properties: ");
                for (int i=0; i<propInfo.inverse.size();i++) {
                    totalInfo=totalInfo.concat(((Resource)propInfo.inverse.elementAt(i)).getLocalName());
                    if (i!=propInfo.inverse.size()-1) totalInfo=totalInfo.concat(", ");
                }
                if (propInfo.inverse.size()==0) totalInfo=totalInfo.concat("-");
            }
            
            infoArea.setText(totalInfo);
        }
    }
    
    
    public void dragDropEnd(DragSourceDropEvent event) {
        if ( event.getDropSuccess()){
            //removeElement();
        }
    }
    
    
    public void dragExit(DragSourceEvent event) {
        //System.out.println( "dragExit");
        
    }
    
    
    public void dropActionChanged( DragSourceDragEvent event) {
        //System.out.println( "dropActionChanged");
    }
    
    public void dragOver(DragSourceDragEvent event) {
        //System.out.println( "dragOver");
        
    }
    
    public void dragEnter(DragSourceDragEvent event) {
        //System.out.println( " dragEnter");
    }
    
    
    public void dragGestureRecognized( DragGestureEvent event) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)ontTree.getLastSelectedPathComponent();
        if (node == null)
            return;
        Object selected = node.getUserObject();
        if ( selected != null ){
            
            StringSelection text = new StringSelection( selected.toString());
            
            // as the name suggests, starts the dragging
            dragSource.startDrag(event, DragSource.DefaultMoveDrop, text, this);
            
        } else {
            System.out.println( "nothing was selected");
        }
    }
    
    //Handle action events,from buttons such as open,load or save
    public void actionPerformed(ActionEvent event) {
        Object source = event.getSource();
        
        if (source==openButton){
            
            JFileChooser chooser=new JFileChooser();
            OWLFileFilter filter=new OWLFileFilter();
            filter.addExtension("owl");
            filter.setDescription("OWL Files");
            chooser.setFileFilter(filter);
            
            chooser.setDialogTitle("Open the OWL file with the basic ontology");
            
            int answer=0;
            if (mapVector.size()!=0){
                answer=JOptionPane.showConfirmDialog(null,"You are about to open a new ontology.Are you sure you want to proceed without first saving your mappings?",
                        "Open New Ontology",JOptionPane.YES_NO_OPTION,
                        JOptionPane.WARNING_MESSAGE);
            }
            if (answer==JOptionPane.YES_OPTION){
                int returnVal = chooser.showOpenDialog(this);
                if (returnVal == JFileChooser.APPROVE_OPTION) {
                    
                    infoArea.setText(null);
                    
                    newFilePath="file:/";
                    newFilePath=newFilePath.concat(chooser.getSelectedFile().getPath());
                    String suffix = new String();
                    if (newFilePath.contains(".")) suffix=newFilePath.substring(newFilePath.lastIndexOf('.')+1);
                    if (!suffix.equalsIgnoreCase("owl")){
                        JOptionPane.showMessageDialog(null,"Make sure the file name ends in .owl",
                                "File Format Not Supported",
                                JOptionPane.ERROR_MESSAGE);
                    } else{
                        //if a different OWL file is opened,initialize the GUI components
                        if (!oldFilePath.equals(newFilePath)){
                            
                            mapVector.removeAllElements();
                            mapList.setListData(mapVector);
                            txtVersion.setText(null);
                            txtDB.setText(null);
                            txtFile.setText(null);
                            
                            
                            
                            
                            ontModel= ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM, null );
                            try{
                                ontModel.read( newFilePath,"",null );
                            }catch(Exception ex){
                                JOptionPane.showMessageDialog(null,"This file cannot be properly opened due to connection or wrong file format reasons.\nMake sure that you are online and that you have opened a legal OWL file",
                                        "Error in opening file",
                                        JOptionPane.ERROR_MESSAGE);
                            }
                            //show the class hierarchy
                            ch.showHierarchy( ontModel );
                            treeModel= ch.treeModel;
                            ontTree.setModel(treeModel);
                            
                            //show the property hierarchy
                            ph.showHierarchy( ontModel );
                            propModel= ph.treeModel;
                            propTree.setModel(propModel);
                            
                            oldFilePath=newFilePath;
                        }
                    }
                }
            }
        }
        
        //loads an OWL file that already contains some mappings
        else if (source==loadButton){
            JFileChooser chooser=new JFileChooser();
            OWLFileFilter filter=new OWLFileFilter();
            filter.addExtension("owl");
            filter.setDescription("OWL Files");
            chooser.setFileFilter(filter);
            
            chooser.setApproveButtonText("Load");
            chooser.setDialogTitle("Load an OWL file with existing mappings");
            
            int returnVal = chooser.showOpenDialog(this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                boolean acceptLoading =true;
                String oldLocalName=oldFilePath.substring(oldFilePath.lastIndexOf('\\')+1);
                if (ontModel==null){
                    JOptionPane.showMessageDialog(null,"Please open first your basic ontology before loading any existent mappings",
                            "No Ontology Loaded",
                            JOptionPane.ERROR_MESSAGE);
                } else{
                    loadedFile=chooser.getSelectedFile().getPath();
                    
                    
                    String suffix = new String();
                    if (loadedFile.contains(".")) suffix=loadedFile.substring(loadedFile.lastIndexOf('.')+1);
                    if (!suffix.equalsIgnoreCase("owl")){
                        JOptionPane.showMessageDialog(null,"Make sure the file name ends in .owl",
                                "File Format Not Supported",
                                JOptionPane.ERROR_MESSAGE);
                    } else{
                        try{
                            loadedOntModel= ModelFactory.createOntologyModel( OntModelSpec.OWL_MEM, null );
                            loadedOntModel.read( "file:/"+loadedFile,"",null );
                            String basePrefix=loadedOntModel.getNsPrefixURI("");
                            
                            //check whether the mappings loaded refer to the ontology opened
                            DatatypeProperty dp=loadedOntModel.getDatatypeProperty(basePrefix+"queryString");
                            if (dp!=null){
                                String fullName=dp.getComment(null);
                                String localName=fullName.substring(fullName.lastIndexOf('\\')+1);
                                if (!localName.equals(oldLocalName)){
                                    acceptLoading=false;
                                    JOptionPane.showMessageDialog(null,"The file you chose does not agree with the ontology opened\n" +
                                            "Please load another file or open another basic ontology",
                                            "Not Proper Mapping File",
                                            JOptionPane.ERROR_MESSAGE);
                                }
                                
                            } else{
                                JOptionPane.showMessageDialog(null,"There are no mappings in this file.Please load a different file",
                                        "No Mappings Found",
                                        JOptionPane.ERROR_MESSAGE);
                                acceptLoading=false;
                            }
                            if (acceptLoading){
                                mapVector.removeAllElements();
                                mapList.setListData(mapVector);
                                //decribe all the queries included in the loaded model,by adding them to the mappings list
                                Property myProp = loadedOntModel.getProperty(basePrefix, "queryString");
                                StmtIterator i = loadedOntModel.listStatements(null, myProp, (RDFNode)null);
                                while (i.hasNext()){
                                    Statement s = i.nextStatement();
                                    String classMapped = s.getSubject().getLocalName();
                                    String mapQuery = s.getString();
                                    describeQuery(classMapped,mapQuery);
                                }
                                txtVersion.setText(dp.getVersionInfo());
                                txtDB.setText(dp.getLabel(null));
                                txtFile.setText(dp.getComment(null));
                                ontModel=loadedOntModel;
                            }
                        }catch(Exception ex){
                            JOptionPane.showMessageDialog(null,"This file cannot be properly loaded due to connection or wrong file format reasons.\nMake sure that you are online and that you have opened a legal OWL file",
                                    "Error in loading file",
                                    JOptionPane.ERROR_MESSAGE);
                            ex.printStackTrace();
                        }
                    }
                }
            }
            
            
        }
        
        //saves the current mappings to an OWL file
        else if ((source==saveButton)&&(ontModel!=null)){
            JFileChooser chooser=new JFileChooser();
            OWLFileFilter filter=new OWLFileFilter();
            filter.addExtension("owl");
            filter.setDescription("OWL Files");
            chooser.setFileFilter(filter);
            chooser.setDialogTitle("Save these mappings as an OWL file");
            
            int returnVal = chooser.showSaveDialog(this);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                String saveFile=chooser.getSelectedFile().getPath();
                File f;
                if ((!saveFile.endsWith(".owl"))&&(!saveFile.endsWith(".OWL"))) f=new File(saveFile+".owl");
                else f=new File(saveFile);
                try{
                    String basePrefix=ontModel.getNsPrefixURI("");
                    FileWriter fw=new FileWriter(f);
                    
                    RDFWriter st=ontModel.getWriter("RDF/XML-ABBREV");
                    st.setProperty("xmlbase",basePrefix);
                    st.write(ontModel,fw,basePrefix);
                    fw.close();
                    
                }catch(Exception ex){
                }
                
            }
            
            //removes a mapping from the model and the mapping list
        } else if (source==removeMenuItem){
            try{
                String tobeRemoved=(String) mapList.getSelectedValue();
                mapVector.removeElement(mapList.getSelectedValue());
                mapList.setListData(mapVector);
                
                String basePrefix=ontModel.getNsPrefixURI("");
                String classtoRemove=tobeRemoved.substring(0,tobeRemoved.indexOf('-'));
                OntClass myClass= ontModel.getOntClass(basePrefix+classtoRemove);
                OntProperty myProp = ontModel.getOntProperty(basePrefix+"queryString");
                Property myProp2 = ontModel.getProperty(basePrefix,"queryString");
                StmtIterator i = ontModel.listStatements(myClass, myProp2, (RDFNode)null);
                Vector tmp=new Vector();
                while (i.hasNext()){
                    Statement s = i.nextStatement();
                    tmp.addElement(s.getSubject());
                }
                for (int j=0;j<tmp.size();j++){
                    Resource res=(Resource)tmp.elementAt(j);
                    res.removeAll(myProp);
                    myProp.removeDomain(res);
                }
                //if there are no more mappings,remove completely the property "queryString"
                if (mapVector.size()==0) {
                    myProp.remove();
                    txtVersion.setText(null);
                    txtDB.setText(null);
                    txtFile.setText(null);
                }
            }catch(Exception ex){}
        }
        //removes all mappings from the model and from the mapping list
        else if (source==removeAllMenuItem){
            mapVector.removeAllElements();
            mapList.setListData(mapVector);
            txtVersion.setText(null);
            txtDB.setText(null);
            txtFile.setText(null);
            
            String basePrefix=ontModel.getNsPrefixURI("");
            OntProperty myProp = ontModel.getOntProperty(basePrefix+"queryString");
            //remove version info and label from the model
            if (myProp!=null){
                String info=myProp.getVersionInfo();
                myProp.removeVersionInfo(info);
                info=myProp.getLabel(null);
                if (info!=null) myProp.removeLabel(info,null);
                info=myProp.getComment(null);
                if (info!=null) myProp.removeComment(info,null);
                
                //remove property queryString from all the classes containing it,and then remove it totally from the model
                Property myProp2 = ontModel.getProperty(basePrefix,"queryString");
                StmtIterator i = ontModel.listStatements(null, myProp2, (RDFNode)null);
                Vector tmp=new Vector();
                while (i.hasNext()){
                    com.hp.hpl.jena.rdf.model.Statement s = i.nextStatement();
                    tmp.addElement(s.getSubject());
                }
                for (int j=0;j<tmp.size();j++){
                    Resource res=(Resource)tmp.elementAt(j);
                    res.removeAll(myProp);
                    myProp.removeDomain(res);
                }
                myProp.remove();
            }
            
        }
        
    }
    
    //describe all the mappings included in the model and add them to the mapping list
    public void describeQuery(String classMapped,String strQuery){
        
        String description=classMapped+"---->";
        if (strQuery.contains("*")){
            description=description.concat("Table(s): ");
            //get the tables after FROM
            if (strQuery.contains("WHERE"))
                description=description.concat(strQuery.substring(strQuery.indexOf(" FROM ")+6,strQuery.indexOf(" WHERE ")));
            else
                description=description.concat(strQuery.substring(strQuery.indexOf(" FROM ")+6));
        } else{
            description=description.concat("Field(s): ");
            //find the fields after SELECT
            description=description.concat(strQuery.substring(7,strQuery.indexOf(" FROM ")));
        }
        if (strQuery.contains("WHERE")){
            description=description.concat(" with condition(s):");
            description=description.concat(strQuery.substring(strQuery.indexOf(" WHERE ")+7));
            
        }
        
        mapVector.addElement(description);
        mapList.setListData(mapVector);
        
    }
    
    
}

